// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.plugins.gradle.service.task

import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId
import com.intellij.openapi.externalSystem.service.execution.ExternalSystemRunnableState
import org.gradle.util.GradleVersion
import org.jetbrains.annotations.ApiStatus
import org.jetbrains.plugins.gradle.service.execution.joinInitScripts
import org.jetbrains.plugins.gradle.service.project.GradleProjectResolverExtension
import org.jetbrains.plugins.gradle.service.project.GradleProjectResolverUtil
import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings

@ApiStatus.Internal
@Suppress("DEPRECATION")
class GradleTaskManagerExtensionResolverBridge : GradleTaskManagerExtension {

  override fun configureTasks(
    projectPath: String,
    id: ExternalSystemTaskId,
    settings: GradleExecutionSettings,
    gradleVersion: GradleVersion?,
  ) {
    val project = id.findProject()
    val taskNames = settings.tasks
    val enhancementParameters = createEnhancementParameters(settings, gradleVersion)

    GradleProjectResolverUtil.createProjectResolvers(null).forEachOrdered { resolverExtension ->
      val resolverClassName = resolverExtension.javaClass.name

      val initScripts = ArrayList<String>()
      val executionEnvironmentVariables = resolverExtension.enhanceTaskProcessing(project, taskNames, { script ->
        if (!script.isNullOrEmpty()) {
          initScripts.add("//-- Generated by $resolverClassName")
          initScripts.add(script)
          initScripts.add("//")
        }
      }, enhancementParameters)

      if (!initScripts.isEmpty()) {
        val initScript = joinInitScripts(initScripts)
        settings.addInitScript(RESOLVER_SCRIPT_NAME, initScript)
      }

      settings.withEnvironmentVariables(executionEnvironmentVariables)
    }
  }

  private fun createEnhancementParameters(
    settings: GradleExecutionSettings,
    gradleVersion: GradleVersion?,
  ): Map<String, String> {
    return buildMap {
      val jvmParameters = settings.jvmParameters
      if (jvmParameters != null) {
        put(GradleProjectResolverExtension.JVM_PARAMETERS_SETUP_KEY, jvmParameters)
      }

      val isRunAsTest = settings.isRunAsTest
      put(GradleProjectResolverExtension.IS_RUN_AS_TEST_KEY, isRunAsTest.toString())
      val isBuiltInTestEventsUsed = settings.isBuiltInTestEventsUsed
      put(GradleProjectResolverExtension.IS_BUILT_IN_TEST_EVENTS_USED_KEY, isBuiltInTestEventsUsed.toString())

      val debugDispatchPort = settings.getUserData(ExternalSystemRunnableState.DEBUGGER_DISPATCH_PORT_KEY)
      if (debugDispatchPort != null) {
        put(GradleProjectResolverExtension.DEBUG_DISPATCH_PORT_KEY, debugDispatchPort.toString())
      }
      val debugOptions = settings.getUserData(ExternalSystemRunnableState.DEBUGGER_PARAMETERS_KEY)
      if (debugOptions != null) {
        put(GradleProjectResolverExtension.DEBUG_OPTIONS_KEY, debugOptions)
      }
      val debugDispatchAddr = settings.getUserData(ExternalSystemRunnableState.DEBUGGER_DISPATCH_ADDR_KEY)
      if (debugDispatchAddr != null) {
        put(GradleProjectResolverExtension.DEBUG_DISPATCH_ADDR_KEY, debugDispatchAddr)
      }

      if (gradleVersion != null) {
        put(GradleProjectResolverExtension.GRADLE_VERSION, gradleVersion.version)
      }
    }
  }

  companion object {

    private const val RESOLVER_SCRIPT_NAME = "ijresolvers"
  }
}
